import type { MapOption } from './types'
import config from '@/config'

import { get as getProjection } from 'ol/proj'
import { containsExtent, getTopLeft, getWidth } from 'ol/extent'
import TileLayer from 'ol/layer/Tile'
import WMTS from 'ol/source/WMTS'
import WMTSTileGrid from 'ol/tilegrid/WMTS'
import View from 'ol/View'
import { defaults as defaultControls, MousePosition } from 'ol/control'
import { createStringXY } from 'ol/coordinate'
import Overlay from 'ol/Overlay'
import VectorSource from 'ol/source/Vector'
import VectorLayer from 'ol/layer/Vector'
import Map from 'ol/Map'
import DoubleClickZoom from 'ol/interaction/DoubleClickZoom'

class MapUtils {
  map?: Map
  view?: View
  popup?: Overlay
  mousePositionControl?: MousePosition
  tempSource: any
  tempLayer?: VectorLayer<any>
  vecLayer?: TileLayer<WMTS>
  imgLayer?: TileLayer<WMTS>
  cvaLayer?: TileLayer<WMTS>
  // 是否已经渲染成功
  isAreadyInit?: boolean

  // constructor(options: any) {
  //   this.map = options.map
  //   this.popup = options.popup
  //   this.mousePositionControl = options.mousePositionControl
  //   this.tempSource = options.tempSource
  //   this.tempLayer = options.tempLayer
  //   this.vecLayer = options.vecLayer
  //   this.imgLayer = options.imgLayer
  //   this.cvaLayer = options.cvaLayer
  //   this.isAreadyInit = options.isAreadyInit
  // }

  initMap(options: MapOption) {
    const layersOption = new Array() // 初始化图层
    const EPSG = 'EPSG:4326'
    // let mapType = config.map.type // 根据开发和生产使用不同厂商的底图能力
    const mapType = Math.random() > 0.1 ? 'tianditu' : 'aimap'
    // 矢量底图
    const vecSign = 'vec'
    const vecUrl = config.map.wmtsUrl_1 + (mapType === 'tianditu' ? config.map.webKey : 'ak')
    this.vecLayer = this.initWMTSTile(vecUrl, vecSign, EPSG)

    // 卫星地图
    const imgSign = 'img'
    const imgUrl = config.map.wmtsUrl_3 + (mapType === 'tianditu' ? config.map.webKey : 'ak')
    this.imgLayer = this.initWMTSTile(imgUrl, imgSign, EPSG)
    this.imgLayer.setVisible(false)

    // 矢量注记
    const cvaSign = 'cva'
    const cvaUrl = config.map.wmtsUrl_2 + (mapType === 'tianditu' ? config.map.webKey : 'ak')
    this.cvaLayer = this.initWMTSTile(cvaUrl, cvaSign, EPSG)

    layersOption.push(this.vecLayer, this.imgLayer, this.cvaLayer)

    // 视图层
    this.view = new View({
      center: options.center,
      projection: getProjection(EPSG)!,
      zoom: options.zoom,
      minZoom: options.minZoom,
      maxZoom: options.maxZoom
    })

    // 显示鼠标光标位置坐标的控件
    this.mousePositionControl = new MousePosition({
      coordinateFormat: createStringXY(4), // 保留四位小数
      projection: EPSG,
      className: 'custom-mouse-position',
      target: 'mouse-position'
      // undefinesHTML: '&nbsp;'
    })

    // 初始地图弹窗
    const container = document.getElementById('popup')!!
    this.popup = new Overlay({
      element: container,
      autoPan: {
        animation: {
          duration: 250
        }
      } // 地图定位时平滑移动
    })

    // 临时矢量图层
    this.tempSource = new VectorSource({
      features: []
    })
    this.tempLayer = new VectorLayer({
      className: 'tempLayer',
      source: this.tempSource
    })
    layersOption.push(this.tempLayer)

    // 地图实例
    this.map = new Map({
      controls: defaultControls({
        attribution: true, // 图层筛选
        rotate: true,
        zoom: true
      }),
      layers: layersOption,
      overlays: [this.popup],
      target: options.target,
      view: this.view
    })

    // 添加控件
    this.map.addControl(this.mousePositionControl)

    /* 移除地图双击缩放的操作 - 移除操作示例 */
    const dblClickInteraction = this.map
      .getInteractions() // Get the map interactions. Modifying this collection changes the interactions associated with the map. Interactions are used for e.g. pan, zoom and rotate.
      .getArray()
      .find((interaction) => {
        return interaction instanceof DoubleClickZoom
      })!
    this.map.removeInteraction(dblClickInteraction)
    /* 移除地图双击缩放的操作 */

    this.isAreadyInit = true

    return this.map
  }

  // 渲染基础地图瓦片图层
  initWMTSTile(url: string, type: string, epsg: string, style?: string | undefined) {
    const projection = getProjection(epsg) // 获取当前底图类型的对象
    const projectionExtent = projection?.getExtent()!
    const size = getWidth(projectionExtent) / 256
    const resolutions = new Array(18)
    const matrixIds = new Array(18)
    for (let z = 1; z < 19; ++z) {
      resolutions[z] = size / Math.pow(2, z)
      matrixIds[z] = z
    }

    return new TileLayer({
      opacity: 1,
      source: new WMTS({
        url: url,
        layer: type,
        matrixSet: 'c',
        format: 'tiles',
        style: style || 'default',
        projection: projection!,
        tileGrid: new WMTSTileGrid({
          origin: getTopLeft(projectionExtent),
          resolutions: resolutions,
          matrixIds: matrixIds
        }),
        wrapX: true
      })
    })
  }

  // 添加弹窗覆盖物
  /**
   * @param idName dom id 名
   * @param clickCoordinate 坐标点point[lng, lat]
   */
  addPopup(idName: string, clickCoordinate: number[]) {
    this.popup = new Overlay({
      element: document.getElementById(idName)!,
      autoPan: {
        animation: {
          duration: 250
        }
      } // 地图定位时平滑移动
    })
    this.popup?.setPosition(clickCoordinate)
    if (this.popup) {
      this.map?.addOverlay(this.popup)
    }
  }

  /**
   * 清除弹窗覆盖物
   */
  removePopupOverlay() {
    const res = this.map?.getOverlays()
    console.log('%c [ res ]-192', 'font-size:13px; background:#d6263c; color:#ff6a80;', res)
    if (!this.popup) {
      return
    }
    this.map?.removeOverlay(this.popup)
  }
}

export default MapUtils
